package com.example.opengldemo;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class Lvs_OpenGl_Interface_Android implements GLSurfaceView.Renderer {


    private static float[] vertexVertices={
            -1,-1,
            1,-1,
            -1,1,
            1,1,
    };

    private static float[] textureVertices={
           0,1,
           1,1,
           0,0,
           1,0,
    };

    private static final String vertexShaderString=
                    "attribute vec4 vertexIn;"+
                    "attribute vec2 textureIn;"+
                    "varying vec2 textureOut;"+
                    "void main(){"+
                            "gl_Position=vertexIn;"+
                            "textureOut = textureIn;"+
                            "}";

    private static final String yuvFragmentShaderString =
            "precision mediump float;"+
                    "uniform sampler2D tex_y;"+
                    "uniform sampler2D tex_u;"+
                    "uniform sampler2D tex_v;"+
                    "varying vec2 textureOut;"+
                    "void main(){"+
                    "vec4 c = vec4((texture2D(tex_y, textureOut).r - 16./255.) * 1.164);" +
                    "vec4 U = vec4(texture2D(tex_u, textureOut).r - 128./255.);" +
                    "vec4 V = vec4(texture2D(tex_v, textureOut).r - 128./255.);" +
                    "c += V * vec4(1.596, -0.813, 0, 0);" +
                    "c += U * vec4(0, -0.392, 2.017, 0);" +
                    "c.a = 1.0;" +
                    "gl_FragColor = c;" +
                    "}";


    //着色器用的顶点属性索引 position是由3个（x,y,z）组成，
    public int ATTRIB_VERTEX = 0;
    //着色器用的像素，纹理属性索引 而颜色是4个（r,g,b,a）
    public int ATTRIB_TEXTURE = 0;

    private GLSurfaceView mTargetSurface;                                                              //外部传入的GLSurfaceView
    public int p = 0;                                                                                    //Program着色器程序的id
    ByteBuffer vertexVertices_buffer = null;                                                           //定义顶点数组
    ByteBuffer textureVertices_buffer = null;                                                          //定义像素纹理数组
    public int m_IsInitShaders = 0;                                                                    //是否已经InitShaders，onSurfaceCreated
//    public Lvs_Play_Interface_Sdk_Android.OpenGl_DisplayCallBackInterface m_displaydatack = null;      //用于显示回调函数，参数数据及时间戳
    public byte m_yuvbuf[] = new byte[640*480*3];												       //存放yuv数据的buf指针，申请buffer在外面
    public ByteBuffer yuvplaner_y = null;                                                               //分用于渲染的变量
    public ByteBuffer yuvplaner_u = null;                                                               //分用于渲染的变量
    public ByteBuffer yuvplaner_v = null;                                                               //分用于渲染的变量;
    public int[] m_millis_realtime = new int[1];                                                      //实时的时间戳，每次回调会更新
    public int m_yuvdata_width = 0;											                            //数据宽
    public int m_yuvdata_height = 0;										                            //数据高
    public int m_frameBuffer = 0;                                                                       //framebuffer
    public int m_renderBuffer = 0;                                                                      //renderbuffer
    public int m_textureid_y, m_textureid_u, m_textureid_v;                                         //纹理的名称，并且，该纹理的名称在当前的应用中不能被再次使用。
    public int m_textureUniformY, m_textureUniformU,m_textureUniformV;

    public Lvs_OpenGl_Interface_Android(GLSurfaceView glSurfaceView){

        mTargetSurface = glSurfaceView;

        mTargetSurface.setEGLContextClientVersion(2);
    }


    void initShaders(){

        createBuffers(vertexVertices,textureVertices);

        p = createProgram(vertexShaderString,yuvFragmentShaderString);

        ATTRIB_VERTEX = GLES20.glGetAttribLocation(p,"vertexIn");
        if(ATTRIB_VERTEX==-1){
            Log.e("androidLog","glGetAttribLocation vertexIn error");
        }

        ATTRIB_TEXTURE = GLES20.glGetAttribLocation(p,"textureIn");
        if(ATTRIB_TEXTURE==-1){
            Log.e("androidLog","glGetAttribLocation textureIn error");
        }

        GLES20.glUseProgram(p);

        m_textureUniformY = GLES20.glGetUniformLocation(p,"tex_y");
        m_textureUniformU = GLES20.glGetUniformLocation(p,"tex_u");
        m_textureUniformV = GLES20.glGetUniformLocation(p,"tex_v");

        int[] textures_y = new int[1];
        GLES20.glGenTextures(1,textures_y,0);
        m_textureid_y = textures_y[0];

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,m_textureid_y);

        //设置该纹理的一些属性
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        int [] textures_u = new int[1];
        GLES20.glGenTextures(1,textures_u,0);
        m_textureid_u = textures_u[0];

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, m_textureid_u);

        //设置该纹理的一些属性
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        int [] textures_v=new int[1];
        GLES20.glGenTextures(1,textures_v,0);
        m_textureid_v = textures_v[0];

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,m_textureid_v);

        //设置该纹理的一些属性
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        return;
    }

    int disPlayImage(long parm){

        if(yuvplaner_y!=null){
            yuvplaner_y.clear();
            yuvplaner_y.put(m_yuvbuf,0,m_yuvdata_width*m_yuvdata_height);
            yuvplaner_y.position(0);
        }

        if(yuvplaner_u!=null){
            yuvplaner_u.clear();
            yuvplaner_u.put(m_yuvbuf,m_yuvdata_width*m_yuvdata_height,m_yuvdata_width*m_yuvdata_height/4);
            yuvplaner_u.position(0);
        }

        if(yuvplaner_v!=null){
            yuvplaner_v.clear();
            yuvplaner_v.put(m_yuvbuf,m_yuvdata_width*m_yuvdata_height*5/4,m_yuvdata_width*m_yuvdata_height/4);
            yuvplaner_v.position(0);
        }

        GLES20.glClearColor(0,0,0,1);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        GLES20.glVertexAttribPointer(ATTRIB_VERTEX,2,GLES20.GL_FLOAT,false,0,vertexVertices_buffer);

        GLES20.glEnableVertexAttribArray(ATTRIB_VERTEX);

        GLES20.glVertexAttribPointer(ATTRIB_TEXTURE,2,GLES20.GL_FLOAT,false,0,textureVertices_buffer);

        GLES20.glEnableVertexAttribArray(ATTRIB_TEXTURE);

        //Y
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,m_textureid_y);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,0,GLES20.GL_LUMINANCE,m_yuvdata_width,m_yuvdata_height,0,GLES20.GL_LUMINANCE,GLES20.GL_UNSIGNED_BYTE,yuvplaner_y);
        GLES20.glUniform1i(m_textureUniformY,0);

        //U
        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,m_textureid_u);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,0,GLES20.GL_LUMINANCE,m_yuvdata_width/2,m_yuvdata_height/2,0,GLES20.GL_LUMINANCE,GLES20.GL_UNSIGNED_BYTE,yuvplaner_u);
        GLES20.glUniform1i(m_textureUniformU,1);

        //V
        GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,m_textureid_v);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D,0,GLES20.GL_LUMINANCE,m_yuvdata_width/2,m_yuvdata_height/2,0,GLES20.GL_LUMINANCE,GLES20.GL_UNSIGNED_BYTE,yuvplaner_v);
        GLES20.glUniform1i(m_textureUniformV,2);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);
        GLES20.glFlush();;

        GLES20.glDisableVertexAttribArray(ATTRIB_VERTEX);
        GLES20.glDisableVertexAttribArray(ATTRIB_TEXTURE);

        return 1;
    }


    private void createBuffers(float[]vert,float[]coord){

        vertexVertices_buffer = ByteBuffer.allocateDirect(vert.length*4);
        vertexVertices_buffer.order(ByteOrder.nativeOrder());
        vertexVertices_buffer.asFloatBuffer().put(vert);
        vertexVertices_buffer.position(0);

        if(textureVertices_buffer==null){

            textureVertices_buffer = ByteBuffer.allocateDirect(coord.length*4);
            textureVertices_buffer.order(ByteOrder.nativeOrder());
            textureVertices_buffer.asFloatBuffer().put(coord);
            textureVertices_buffer.position(0);
        }
    }

    public int createProgram(String vertexSource,String fragmentSource){

        int vertexShader = loaderShader(GLES20.GL_VERTEX_SHADER,vertexSource);
        int fragmentShader = loaderShader(GLES20.GL_FRAGMENT_SHADER,fragmentSource);

        int program = GLES20.glCreateProgram();
        if(program!=0){
            GLES20.glAttachShader(program,vertexShader);
            GLES20.glAttachShader(program,fragmentShader);
            GLES20.glLinkProgram(program);
            int []linkStatus = new int[1];
            GLES20.glGetProgramiv(program,GLES20.GL_LINK_STATUS,linkStatus,0);
            if(linkStatus[0]!=GLES20.GL_TRUE){
                GLES20.glDeleteProgram(program);
                Log.e("androidLog","链接程序失败");
            }
        }
        return program;
    }

    private int loaderShader(int shaderType,String source){

        int shader = GLES20.glCreateShader(shaderType);
        if(shader!=0){
            GLES20.glShaderSource(shader,source);
            GLES20.glCompileShader(shader);
            int[]compiled = new int[1];
            GLES20.glGetShaderiv(shader,GLES20.GL_COMPILE_STATUS,compiled,0);
            if(compiled[0]==0){
                GLES20.glDeleteShader(shader);
                Log.e("androidLog","程序编译失败\n"+source);
            }
        }
        return shader;
    }





    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {

    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int i, int i1) {

    }

    @Override
    public void onDrawFrame(GL10 gl10) {

    }
}
